﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Navigation;
using System.Windows.Shapes;
using AutoLoL.Dialogs;
using AutoLoL.Entities;
using AutoLoL.Logic;
using AutoLoL.Logic.Automation;
using AutoLoL.Logic.Exceptions;
using AutoLoL.Logic.Factories;
using AutoLoL.Logic.Masteries;
using AutoLoL.Logic.Parsers;
using AutoLoL.Logic.Utils;
using AutoLoL.Logic.Windows;
using AutoLoL.Shared;

namespace AutoLoL.Controls
{
    /// <summary>
    /// Interaction logic for EditBuildControl.xaml
    /// </summary>
    public partial class EditBuildControl : UserControl
    {
        private MasteryEditorControl _masteryEditorControl;
        private ChampionBuild _championBuild;
        private Champion _selectedChampion;
        private Item[] _selectedItems;
        private SummonerSpell[] _selectedSpells;

        private TextBlock _guideContent;

        public EditBuildControl(ChampionBuild championBuild)
        {
            InitializeComponent();

            // TODO - Add a value some time
            LastUpdateTextBlock.Visibility = Visibility.Collapsed;

            if (championBuild.ChampionBuildId == null || championBuild.ChampionBuildId == Guid.Empty)
            {
                DeleteButton.Visibility = Visibility.Collapsed;
            }

            //Populate the dropdown
            GameTypeComboBox.ItemsSource = Enum.GetValues(typeof(GameType));

            _championBuild = championBuild;

            SetChampion(championBuild.Champion);
            SetItems(championBuild.Items);
            SetSummonerSpells(championBuild.SummonerSpells);

            GameTypeComboBox.SelectedItem = _championBuild.GameType;

            TitleTextBox.Text = championBuild.Title;

            // Copy the mastery build and feed it to the editor control
            MasteryBuild masteryBuild = MasteryFactory.Instance.GetMasteryBuild();
            MasteryBuildManager manager = new MasteryBuildManager(masteryBuild, MasteryFactory.Instance, SummonerSpellFactory.Instance);
            manager.FromMasteryBuild(championBuild.MasteryBuild);
            _masteryEditorControl = new MasteryEditorControl(masteryBuild);
            MasteryEditorViewbox.Child = _masteryEditorControl;

            GuideTextBox.Text = championBuild.Guide;

            ViewButton_Click(null, null);
        }

        private void SetChampion(Champion champion)
        {
            _selectedChampion = champion;
            ChampionImage.Source = champion.IconBitmapImage;
            ChampionNameTextBlock.Text = champion.Name;
            ChampionDescriptionTextBlock.Text = champion.Description;
        }

        private void SetItems(Item[] items)
        {
            _selectedItems = items;

            Grid[] grids = new Grid[] { Item1Grid, Item2Grid, Item3Grid, Item4Grid, Item5Grid, Item6Grid };

            for (int i = 0; i < grids.Length; i++)
            {
                grids[i].DataContext = items[i];
            }
        }

        private void SetSummonerSpells(SummonerSpell[] summonerSpells)
        {
            _selectedSpells = summonerSpells;

            Grid[] grids = new Grid[] { Spell1Grid, Spell2Grid };

            for (int i = 0; i < grids.Length; i++)
            {
                grids[i].DataContext = summonerSpells[i];
            }
        }

        private void ChampionGrid_MouseDown(object sender, MouseButtonEventArgs e)
        {
            ChampionDialog dialog = new ChampionDialog(Window.GetWindow(this), null);
            dialog.ShowDialog();

            if (dialog.SelectedChampions != null)
            {
                Champion champion = dialog.SelectedChampions[0];
                SetChampion(champion);
            }
        }

        private void RunButton_Click(object sender, RoutedEventArgs e)
        {
            
            try
            {
                MASTERY_WINDOWS targetWindow = MASTERY_WINDOWS.None;

                while (true)
                {
                    try
                    {
                        AutoClicker.Click(_masteryEditorControl.MasteryBuild, targetWindow, UserSettings.Instance.IsManualReturnEnabled);
                    }
                    catch (MasteriesNotDetectedException ex2)
                    {
                        Window.GetWindow(this).Activate();

                        SelectWindowDialog dialog = new SelectWindowDialog();
                        dialog.ShowDialog();

                        if (dialog.MasteryWindow != null)
                        {
                            targetWindow = dialog.MasteryWindow.Value;
                            continue; // Restart the loop
                        }
                        else
                        {
                            break;
                        }
                    }

                    break;
                }
            }
            catch (Exception ex1)
            {
                Window.GetWindow(this).Activate();

                string message = ex1.Message;
                ConfirmDialog dialog = new ConfirmDialog(Window.GetWindow(this), message, "Error", false);
                dialog.ShowDialog();
            }
        }

        private void ImportButton_Click(object sender, RoutedEventArgs e)
        {
            ImportDialog dialog = new ImportDialog(Window.GetWindow(this));
            dialog.ShowDialog();

            if (!string.IsNullOrEmpty(dialog.ImportResult))
            {
                string result = dialog.ImportResult;

                //Handle Spells
                string sommoner1, sommoner2;
                int pos = result.IndexOf(":");
                if (pos >= 0)
                {
                    sommoner1 = result.Substring(0, pos);
                    result = result.Substring(pos + 1);
                    _selectedSpells[0] = SummonerSpellFactory.Instance.GetByName(sommoner1, MasteryFactory.Instance);

                    pos = result.IndexOf(":");
                    if (pos >= 0)
                    {
                        sommoner2 = result.Substring(0, pos);
                        result = result.Substring(pos + 1);
                        _selectedSpells[1] = SummonerSpellFactory.Instance.GetByName(sommoner2, MasteryFactory.Instance);
                        SetSummonerSpells(_selectedSpells);
                    }
                }

                MasteryBuildManager manager = new MasteryBuildManager(_masteryEditorControl.MasteryBuild, MasteryFactory.Instance, SummonerSpellFactory.Instance);
                manager.FromString(result);
            }
        }

        private void ImportDefaultItemsButton_Click(object sender, RoutedEventArgs e)
        {
            ImportDefaultItemDialog dialog = new ImportDefaultItemDialog(Window.GetWindow(this), _selectedChampion, (GameType)GameTypeComboBox.SelectedItem);
            dialog.ShowDialog();

            if (dialog.ImportResult != null)
            {
                SetItems(dialog.ImportResult);
            }
        }

        private void ViewButton_Click(object sender, RoutedEventArgs e)
        {
            GuideTextBox.Visibility = System.Windows.Visibility.Collapsed;
            GuideScrollViewer.Visibility = System.Windows.Visibility.Visible;
            ViewButton.Visibility = System.Windows.Visibility.Collapsed;
            EditButton.Visibility = System.Windows.Visibility.Visible;

            _guideContent = BBCodeParser.Parse(GuideTextBox.Text) as TextBlock;

            GuideGrid.Children.Clear();
            GuideGrid.Children.Add(_guideContent);

            SetHyperlinkEvents(_guideContent.Inlines.FirstInline);
        }

        private void EditButton_Click(object sender, RoutedEventArgs e)
        {
            GuideTextBox.Visibility = System.Windows.Visibility.Visible;
            GuideScrollViewer.Visibility = System.Windows.Visibility.Collapsed;
            ViewButton.Visibility = System.Windows.Visibility.Visible;
            EditButton.Visibility = System.Windows.Visibility.Collapsed;
        }

        private void SaveButton_Click(object sender, RoutedEventArgs e)
        {
            _championBuild.Title = TitleTextBox.Text;
            _championBuild.Champion = _selectedChampion;
            _championBuild.Items = _selectedItems;
            _championBuild.SummonerSpells = _selectedSpells;
            _championBuild.Guide = GuideTextBox.Text;
            _championBuild.GameType = (GameType)GameTypeComboBox.SelectedItem;

            MasteryBuildManager manager = new MasteryBuildManager(_championBuild.MasteryBuild, MasteryFactory.Instance, SummonerSpellFactory.Instance);
            manager.FromMasteryBuild(_masteryEditorControl.MasteryBuild);

            OnRequestSaveBuild(new RequestSaveBuildArgs(_championBuild));
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            OnRequestCancelBuild(new RequestCancelBuildArgs());
        }

        private void DeleteButton_Click(object sender, RoutedEventArgs e)
        {
            ConfirmDialog dialog = new ConfirmDialog(Window.GetWindow(this), "Are you sure you want to delete this build?");
            dialog.ShowDialog();

            if (dialog.DialogResult.HasValue && dialog.DialogResult.Value)
            {
                OnRequestDeleteBuild(new RequestDeleteBuildArgs(_championBuild));
            }
        }

        private void SetHyperlinkEvents(Inline inline)
        {
            if (inline == null)
            {
                return;
            }

            Hyperlink hyperlink = inline as Hyperlink;
            if (hyperlink != null)
            {
                if (hyperlink.CommandParameter != null)
                {
                    hyperlink.Click += new RoutedEventHandler(Hyperlink_Click);
                }
                else if (hyperlink.NavigateUri != null)
                {
                    hyperlink.RequestNavigate += new RequestNavigateEventHandler(Hyperlink_RequestNavigate);
                }
            }

            if (inline.NextInline != null)
            {
                SetHyperlinkEvents(inline.NextInline);
            }
        }

        private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            Hyperlink hyperlink = sender as Hyperlink;

            try
            {
                string url = hyperlink.NavigateUri.AbsoluteUri;

                if (url.StartsWith("http://") || url.StartsWith("https://"))
                {
                    Process.Start(new ProcessStartInfo(url));
                }
            }
            catch { if (Debugger.IsAttached) throw; }

            e.Handled = true;
        }

        private void Hyperlink_Click(object sender, RoutedEventArgs e)
        {
            Hyperlink hyperlink = sender as Hyperlink;

            try
            {
                BringInlineIntoView(_guideContent.Inlines.FirstInline, hyperlink.CommandParameter.ToString());
            }
            catch { if (Debugger.IsAttached) throw; }
        }

        private void BringInlineIntoView(Inline inline, string tag)
        {
            if (inline.Tag != null && inline.Tag.Equals(tag))
            {
                inline.BringIntoView();
                return;
            }

            if (inline.NextInline != null)
            {
                BringInlineIntoView(inline.NextInline, tag);
            }
        }

        private void ItemGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Grid[] grids = new Grid[] { Item1Grid, Item2Grid, Item3Grid, Item4Grid, Item5Grid, Item6Grid };

            int index = -1;
            for (int i = 0; i < grids.Length; i++)
            {
                if (grids[i] == sender)
                {
                    index = i;
                    break;
                }
            }

            if (index != -1)
            {
                ItemDialog dialog = new ItemDialog(Window.GetWindow(this), _selectedItems[index]);
                dialog.ShowDialog();

                if (dialog.SelectedItem != null)
                {
                    if (dialog.SelectedItem.Name.ToLower().Equals("none"))
                    {
                        // Deselect item
                        _selectedItems[index] = null;
                    }
                    else
                    {
                        // Select item
                        Item item = dialog.SelectedItem;
                        _selectedItems[index] = item;
                    }

                    SetItems(_selectedItems);
                }
            }
        }

        private void SwapButton_Click(object sender, RoutedEventArgs e)
        {
            SummonerSpell spell1 = _selectedSpells[0];
            SummonerSpell spell2 = _selectedSpells[1];

            _selectedSpells[0] = spell2;
            _selectedSpells[1] = spell1;

            SetSummonerSpells(_selectedSpells);
        }

        private void SpellGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Grid[] grids = new Grid[] { Spell1Grid, Spell2Grid };

            int index = -1;
            for (int i = 0; i < grids.Length; i++)
            {
                if (grids[i] == sender)
                {
                    index = i;
                    break;
                }
            }

            if (index != -1)
            {
                SummonerSpellDialog dialog = new SummonerSpellDialog(Window.GetWindow(this), _masteryEditorControl.MasteryBuild.ImprovedSummonerSpells);
                dialog.ShowDialog();

                if (dialog.SelectedSpell != null)
                {
                    if (dialog.SelectedSpell.Name.ToLower().Equals("none"))
                    {
                        // Deselect item
                        _selectedSpells[index] = null;
                    }
                    else
                    {
                        // Select item
                        SummonerSpell spell = dialog.SelectedSpell;
                        _selectedSpells[index] = spell;
                    }

                    SetSummonerSpells(_selectedSpells);
                }
            }
        }

        public event RequestSaveBuild RequestSaveBuild;
        protected virtual void OnRequestSaveBuild(RequestSaveBuildArgs e)
        {
            if (RequestSaveBuild != null)
            {
                RequestSaveBuild(this, e);
            }
        }

        public event RequestCancelBuild RequestCancelBuild;
        protected virtual void OnRequestCancelBuild(RequestCancelBuildArgs e)
        {
            if (RequestCancelBuild != null)
            {
                RequestCancelBuild(this, e);
            }
        }

        public event RequestDeleteBuild RequestDeleteBuild;
        protected virtual void OnRequestDeleteBuild(RequestDeleteBuildArgs e)
        {
            if (RequestDeleteBuild != null)
            {
                RequestDeleteBuild(this, e);
            }
        }

        private void onDeployItems(object sender, RoutedEventArgs e)
        {
            AutoDeploy.readFromFile(_selectedChampion.DirectoryName, _championBuild.GameType);
            AutoDeploy.addSet(_selectedChampion.DirectoryName, _championBuild.GameType, _selectedItems, 1, _championBuild.Title);
            AutoDeploy.Deploy();
            MessageBox.Show("Deployed default items for " + _selectedChampion.Name + ", set \"" + _championBuild.Title + "\".");
        }
    }

    public delegate void RequestSaveBuild(object sender, RequestSaveBuildArgs e);
    public class RequestSaveBuildArgs : System.EventArgs
    {
        public RequestSaveBuildArgs(ChampionBuild championBuild)
        {
            this.ChampionBuild = championBuild;
        }

        public ChampionBuild ChampionBuild { get; private set; }
    }

    public delegate void RequestCancelBuild(object sender, RequestCancelBuildArgs e);
    public class RequestCancelBuildArgs : System.EventArgs
    {
    }

    public delegate void RequestDeleteBuild(object sender, RequestDeleteBuildArgs e);
    public class RequestDeleteBuildArgs : System.EventArgs
    {
        public RequestDeleteBuildArgs(ChampionBuild championBuild)
        {
            this.ChampionBuild = championBuild;
        }

        public ChampionBuild ChampionBuild { get; private set; }
    }
}
